home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nslookup / RCS / send.c,v < prev    next >
Encoding:
Text File  |  1988-11-27  |  6.1 KB  |  279 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     88.11.23.13.39.22;  author douglis;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @original src from monet.
  17. @
  18.  
  19.  
  20.  
  21. 1.1
  22. log
  23. @Initial revision
  24. @
  25. text
  26. @/*
  27.  * Copyright (c) 1985 Regents of the University of California.
  28.  * All rights reserved.
  29.  *
  30.  * Redistribution and use in source and binary forms are permitted
  31.  * provided that the above copyright notice and this paragraph are
  32.  * duplicated in all such forms and that any documentation,
  33.  * advertising materials, and other materials related to such
  34.  * distribution and use acknowledge that the software was developed
  35.  * by the University of California, Berkeley.  The name of the
  36.  * University may not be used to endorse or promote products derived
  37.  * from this software without specific prior written permission.
  38.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  39.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  40.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  41.  */
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@@(#)send.c    5.9 (Berkeley) 6/18/88";
  45. #endif /* not lint */
  46.  
  47. /*
  48.  *******************************************************************************
  49.  *
  50.  *  send.c --
  51.  *
  52.  *    Routine to send request packets to a name server.
  53.  *
  54.  *    Modified version of 4.3BSD BIND  res_send.c 5.5 (Berkeley) 9/14/85
  55.  *
  56.  *******************************************************************************
  57.  */
  58.  
  59. #include <sys/types.h>
  60. #include <sys/time.h>
  61. #include <sys/socket.h>
  62. #include <netinet/in.h>
  63. #include <stdio.h>
  64. #include <arpa/nameser.h>
  65. #include <resolv.h>
  66. #include "res.h"
  67.  
  68. /*
  69.  *  Initialize the socket address info struct.
  70.  */
  71.  
  72. static struct sockaddr_in sin = { 
  73.     AF_INET,  
  74. };
  75.  
  76.  
  77. /*
  78.  *******************************************************************************
  79.  *
  80.  *   SendRequest --
  81.  *
  82.  *    Sends a request packet to a name server whose address
  83.  *    is specified by the first argument and returns with
  84.  *    the answer packet.
  85.  *
  86.  *  Results:
  87.  *    SUCCESS        - the request was sent and an answer 
  88.  *              was received.
  89.  *    TIME_OUT    - the virtual circuit connection timed-out 
  90.  *              or a reply to a datagram wasn't received.
  91.  *
  92.  *
  93.  *******************************************************************************
  94.  */
  95.  
  96. int
  97. SendRequest(nsAddrPtr, buf, buflen, answer, anslen, trueLenPtr)
  98.     struct in_addr     *nsAddrPtr;
  99.     char         *buf;
  100.     int         buflen;
  101.     char         *answer;
  102.     int         anslen;
  103.     int         *trueLenPtr;
  104. {
  105.     struct timeval     timeout;
  106.     register int     n;
  107.     u_short     packetId, len;
  108.     short         length;
  109.     char         *cp;
  110.     int         retry, v_circuit, resplen;
  111.     int         dsmask;
  112.  
  113.     int         numTimeOuts    = 0;
  114.     HEADER         *requestPtr    = (HEADER *) buf;
  115.     HEADER         *answerPtr    = (HEADER *) answer;
  116.  
  117.  
  118.     if (_res.options & RES_DEBUG2) {
  119.         printf("------------\nSendRequest(), len %d\n", buflen);
  120.         Print_query(buf, buf+buflen, 1);
  121.     }
  122.     sockFD = -1;
  123.  
  124.     /*
  125.      * See if a virtual circuit is required or desired.
  126.      */
  127.     v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
  128.  
  129.     packetId = requestPtr->id;
  130.  
  131.     sin.sin_port    = htons(NAMESERVER_PORT);
  132.     sin.sin_addr    = *nsAddrPtr;
  133.  
  134.     /*
  135.      * Send request, RETRY times, or until successful
  136.      */
  137.     for (retry = _res.retry; --retry >= 0; ) {
  138.         if (v_circuit) {
  139.             /*
  140.              * Use virtual circuit.
  141.              */
  142.             if (sockFD < 0)
  143.                 sockFD = socket(AF_INET, SOCK_STREAM, 0);
  144.  
  145.             if (connect(sockFD, &sin, sizeof(sin)) < 0) {
  146.                 if (_res.options & RES_DEBUG) {
  147.                     perror("SendRequest");
  148.                 }
  149.                 (void) close(sockFD);
  150.                 sockFD = -1;
  151.                 continue;
  152.             }
  153.             /*
  154.              * Send length & message
  155.              */
  156.             len = htons(buflen);
  157.             if (write(sockFD, &len, sizeof(len)) != sizeof(len) ||
  158.                 write(sockFD, buf, buflen) != buflen) {
  159.                 if (_res.options & RES_DEBUG) {
  160.                     perror("SendRequest");
  161.                 }
  162.                 (void) close(sockFD);
  163.                 sockFD = -1;
  164.                 continue;
  165.             }
  166.             /*
  167.              * Receive length & response
  168.              */
  169.             cp = answer;
  170.             length = sizeof(short);
  171.             while(length > 0 && (n = read(sockFD, cp, length)) > 0){
  172.                 cp += n;
  173.                 length -= n;
  174.             }
  175.             if (n <= 0) {
  176.                 if (_res.options & RES_DEBUG) {
  177.                     perror("SendRequest");
  178.                 }
  179.                 (void) close(sockFD);
  180.                 sockFD = -1;
  181.                 continue;
  182.             }
  183.             cp = answer;
  184.             resplen = length = ntohs(*(short *)cp);
  185.             while(length > 0 && (n = read(sockFD, cp, length)) > 0){
  186.                 cp += n;
  187.                 length -= n;
  188.             }
  189.             if (n <= 0) {
  190.                 if (_res.options & RES_DEBUG) {
  191.                     perror("SendRequest");
  192.                 }
  193.                 (void) close(sockFD);
  194.                 sockFD = -1;
  195.                 continue;
  196.             }
  197.         } else {
  198.             /*
  199.              * Use datagrams.
  200.              */
  201.             if (sockFD < 0)
  202.                 sockFD = socket(AF_INET, SOCK_DGRAM, 0);
  203.  
  204.             if (sendto(sockFD, buf, buflen, 0, &sin,
  205.                  sizeof(sin)) != buflen) {
  206.                     perror("SendRequest: sendto");
  207.                     continue;
  208.             }
  209.             /*
  210.              * Wait for reply 
  211.              */
  212.             timeout.tv_sec = _res.retrans;
  213.             timeout.tv_usec = 0;
  214.             dsmask = 1 << sockFD;
  215.             n = select(sockFD+1, &dsmask, 0, 0, &timeout);
  216.             if (n < 0) {
  217.                 if (_res.options & RES_DEBUG) {
  218.                     perror("SendRequest: select");
  219.                 }
  220.                 continue;
  221.             }
  222.             if (n == 0) {
  223.                 /*
  224.                  * timeout
  225.                  */
  226.                 if (_res.options & RES_DEBUG) {
  227.                     printf("Timeout %d\n", ++numTimeOuts);
  228.                 }
  229.                 continue;
  230.             }
  231.              if ((resplen = recv(sockFD, answer, anslen, 0)) <= 0) {
  232.                 if (_res.options & RES_DEBUG) {
  233.                     perror("SendRequest: recv");
  234.                 }
  235.                 continue;
  236.             }
  237.             if (packetId != answerPtr->id) {
  238.                 /*
  239.                  * response from old query, ignore it
  240.                  */
  241.                 if (_res.options & RES_DEBUG2) {
  242.                     printf("------------\nOld answer:\n");
  243.                     Print_query(answer, answer+resplen, 1);
  244.                 }
  245.                 continue;
  246.             }
  247.             if (!(_res.options & RES_IGNTC) && answerPtr->tc) {
  248.                 /*
  249.                  * get rest of answer
  250.                  */
  251.                 if (_res.options & RES_DEBUG) {
  252.                     printf("truncated answer\n");
  253.                 }
  254.                 (void) close(sockFD);
  255.                 sockFD = -1;
  256.                 retry = _res.retry;
  257.                 v_circuit = 1;
  258.                 continue;
  259.             }
  260.         }
  261.         if (_res.options & RES_DEBUG) {
  262.             if (_res.options & RES_DEBUG2) 
  263.             printf("------------\nGot answer (%d bytes):\n",
  264.                 resplen);
  265.             else
  266.             printf("------------\nGot answer:\n");
  267.             Print_query(answer, answer+resplen, 1);
  268.         }
  269.         (void) close(sockFD);
  270.         sockFD = -1;
  271.         *trueLenPtr = resplen;
  272.         return (SUCCESS);
  273.     }
  274.     (void) close(sockFD);
  275.     sockFD = -1;
  276.     return (TIME_OUT);
  277. }
  278. @
  279.